#include "text.hpp"

#include "qbe/src/ecs/app.hpp"

#include "qbe/src/ecs/query.hpp"

#include "qbe/src/axis/axis.hpp"
#include "qbe/src/input/input.hpp"
#include "qbe/src/select/select.hpp"
#include "qbe/src/state/state.hpp"
#include "qbe/src/undoRedo/undoRedo.hpp"
#include "qbe/src/utils/utils.hpp"

#include "qbe/src/layout/layout.hpp"

#include "qlib/all.h"

#include "../components.hpp"
#include "../events.hpp"

#include "qbe/src/ui_message/message.h"

#include <QMessageBox>

#include "../../operationLayer/operationLayer.h"

namespace qbe::draw::text {

// 移除标记
void clear_tag(ecs::Query query) {
  auto param = query.get_resource<Models>();

  if (param.clear_tag) {
    // 获取cell和reg
    auto& cell = query.get_resource<qlib::Cell::s_ptr>();
    auto& reg = cell->reg;

    // 遍历Tag并移除
    auto view_cache_add = reg.view<TextCacheAddTag>();
    view_cache_add.each([&reg](entt::entity e) { reg.remove<TextCacheAddTag>(e); });

    auto view_cache_update = reg.view<TextCacheUpdateTag>();
    view_cache_update.each([&reg](entt::entity e) { reg.remove<TextCacheUpdateTag>(e); });

    auto view_cache_delete = reg.view<TextCacheDeleteTag>();
    view_cache_delete.each([&reg](entt::entity e) { reg.remove<TextCacheDeleteTag>(e); });

    auto view_add = reg.view<TextAddTag>();
    view_add.each([&reg](entt::entity e) { reg.remove<TextAddTag>(e); });
  }
}

// 添加临时对象
void add_cache_obj(entt::registry& reg, ecs::EventWriter<draw::Event> event_writer, layout::LayoutCmd& cmd, entt::entity entity, Models& models,
                   ecs::Query query) {
  auto ptr = reg.get<qlib::Text::s_ptr>(entity);
  auto polygon_arr = ptr->to_polygons();

  models.mesh.meshs.clear();
  models.cache_text = ptr;
  for (auto polygon : polygon_arr) {
    models.mesh.meshs.push_back(render::PolyLineMesh(polygon->points));
  }

  event_writer.send({Code::TextCacheAdd});

  if (models.complete_entity != entt::null) {
    reg.remove<select::SelectTag>(models.complete_entity);
    auto& sele_event_writer = query.get_event_writer<select::Event>();
    sele_event_writer.send({select::Code::SelectUpdate});
    sele_event_writer.send({select::Code::HoverUpdate});

    models.complete_entity = entt::null;
  }
}

// 更新临时对象
void update_cache_obj(entt::registry& reg, ecs::EventWriter<draw::Event> event_writer, layout::LayoutCmd& cmd, entt::entity entity, Models& models) {
  auto ptr = reg.get<qlib::Text::s_ptr>(entity);
  auto polygon_arr = ptr->to_polygons();

  models.mesh.meshs.clear();
  for (auto polygon : polygon_arr) {
    models.mesh.meshs.push_back(render::PolyLineMesh(polygon->points, true));
  }

  event_writer.send({Code::TextCacheUpdate});
}

// 删除临时对象
void delete_cache_obj(entt::registry& reg, ecs::EventWriter<draw::Event> event_writer, layout::LayoutCmd& cmd, entt::entity entity, Models& models) {
  reg.destroy(entity);

  event_writer.send({Code::TextCacheDelete});
}

// 添加对象
void add_obj(entt::registry& reg, ecs::EventWriter<draw::Event> event_writer, layout::LayoutCmd& cmd, entt::entity entity,
             undoRedoT::UndoRedoModule& undoRedoModuel, qlib::Cell::s_ptr cell, Models& models, ecs::Query query, state::State& state) {
  auto ptr = reg.get<qlib::Text::s_ptr>(entity);
  // ptr->layer = state.getCurrentLayer();

  if (models.complete_entity != entt::null) {
    reg.remove<select::SelectTag>(models.complete_entity);
    auto& sele_event_writer = query.get_event_writer<select::Event>();
    sele_event_writer.send({select::Code::SelectUpdate});
    sele_event_writer.send({select::Code::HoverUpdate});

    models.complete_entity = entt::null;
  }

  auto e = cmd.add(ptr);
  models.complete_entity = e;

  undoRedoModuel.start(cell);
  undoRedoModuel.add(e);
  undoRedoModuel.end();

  delete_cache_obj(reg, event_writer, cmd, entity, models);

  models.clear_tag = true;
  reg.emplace<TextAddTag>(e);
  event_writer.send({Code::TextAdd});

  reg.emplace_or_replace<select::SelectTag>(e);
  auto& sele_event_writer = query.get_event_writer<select::Event>();
  sele_event_writer.send({select::Code::SelectUpdate});
  sele_event_writer.send({select::Code::HoverUpdate});
}

// 退出绘制模式时回调
void exit_callback(ecs::Query query, state::AllModeType new_mode) {
  // 获取参数
  auto& param = query.get_resource<Models>();

  // 获取cell和reg
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;
  auto& cmd = query.get_resource<layout::LayoutCmd>();
  auto& models = query.get_resource<Models>();

  // 获取事件写入器
  auto event_writer = query.get_event_writer<draw::Event>();

  // 删除临时对象
  if (param.entity != entt::null)
    delete_cache_obj(reg, event_writer, cmd, param.entity, models);

  if (param.complete_entity != entt::null && !state::isModeType<state::EditingModeType>(new_mode)) {
    reg.remove<select::SelectTag>(param.complete_entity);
    auto& sele_event_writer = query.get_event_writer<select::Event>();
    sele_event_writer.send({select::Code::SelectUpdate});
    sele_event_writer.send({select::Code::HoverUpdate});

    param.complete_entity = entt::null;
  }

  // 重置参数
  param.state = State::None;
  param.entity = entt::null;
  param.is_first_ui = true;
  param.first_open = false;
}

void exit(ecs::Query query) {
  // 获取参数
  auto& param = query.get_resource<Models>();

  // 如果正在绘制
  // 获取cell和reg
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;
  auto& cmd = query.get_resource<layout::LayoutCmd>();
  auto& models = query.get_resource<Models>();

  // 获取事件写入器
  auto event_writer = query.get_event_writer<draw::Event>();

  // 删除临时对象
  if (param.entity != entt::null)
    delete_cache_obj(reg, event_writer, cmd, param.entity, models);

  if (param.complete_entity != entt::null) {
    reg.remove<select::SelectTag>(param.complete_entity);
    auto& sele_event_writer = query.get_event_writer<select::Event>();
    sele_event_writer.send({select::Code::SelectUpdate});
    sele_event_writer.send({select::Code::HoverUpdate});

    param.complete_entity = entt::null;
  }

  // 重置参数
  param.state = State::None;
  param.entity = entt::null;
  param.is_first_ui = true;
  param.first_open = false;

  auto& state = query.get_resource<state::State>();
  state.exit();
}

void init(ecs::Commands command, ecs::Query query) {
  Models param;
  command.insert_resource(param);

  auto& state = query.get_resource<state::State>();
  state.addExitCall(state::DrawingModeType::Text, exit_callback);
}

std::vector<std::string> split(const std::string& s) {
  std::vector<std::string> result;
  std::string current;
  for (char c : s) {
    if (c == ',') {
      result.push_back(current);
      current.clear();
    } else {
      current += c;
    }
  }
  result.push_back(current);
  return result;
}

// 帧开始，模式转换
void stateTransformBegin(Models& param, state::State& state, input::HandleBundle* handle, ecs::Bus& bus) {
  // 执行操作的状态完成则回退，不存在维持情况
  assert(param.state == State::None || param.state == State::Wait);

  // 快捷键
  input::KeyBoardShortcuts kbs;
  kbs.keyBase = vsg::KEY_q;
  kbs.keyModifier = vsg::MODKEY_Shift;

  // 第一次必弹窗
  if (param.is_first_ui && !param.first_open) {
    // 按下则发送事件
    qbe::UiMessage::CreateTextUiOpen event;
    event.reset = true;

    bus.send(event);

    // 等待ui消息
    param.state = State::Wait;
    param.first_open = true;
    return;
  }

  // 如果不处于等待模式，则按下必然弹窗
  if (param.state != State::Wait && handle->keyReleased(kbs)) {
    // 按下则发送事件
    bus.send(qbe::UiMessage::CreateTextUiOpen());

    // 等待ui消息
    param.state = State::Wait;
    return;
  }

  // 等待模式
  if (param.state == State::Wait) {
    // 尝试接收消息
    auto ok_mes = bus.receive<qbe::UiMessage::CreateTextUiOk>();
    auto cancel_mes = bus.receive<qbe::UiMessage::CreateTextUiCancel>();

    // 当确认时ok时
    if (!ok_mes.empty()) {
      param.is_first_ui = false;

      // 获取参数
      param.str = ok_mes.back().str;

      param.string_arr = split(param.str);
      param.count = 0;

      param.str = param.string_arr[param.count % param.string_arr.size()];

      param.rotation = ok_mes.back().rotation;
      param.refer_point_pos = ok_mes.back().refer_point_pos;
      param.layer = ok_mes.back().layer;
      param.size = ok_mes.back().size;

      // 已有则更新
      param.state = State::Upatde;

      return;
    }

    if (!cancel_mes.empty()) {
      if (param.is_first_ui)
        param.state = State::Cancel;
      else
        param.state = State::None;

      param.is_first_ui = false;
      return;
    }
  }

  // 如果不处于弹窗，按esc则取消
  if (param.state != State::Wait && handle->keyReleased(vsg::KEY_Escape)) {
    param.state = State::Cancel;
    return;
  }

  // 如果按下左键，则创建
  if (param.state != State::Wait && handle->mousePressed(vsg::ButtonMask::BUTTON_MASK_1)) {
    param.state = State::Complete;
    return;
  }

  if (param.state != State::Wait && handle->mouse_move) {
    param.state = State::Upatde;
    return;
  }
}

// 帧尾-退出模式
void stateTransformEnd(State& state) {
  // 操作模式执行完就回退
  if (state == State::Upatde || state == State::Complete || state == State::Cancel) {
    state = State::None;
  }
}

void update(ecs::Query query, ecs::Bus& bus) {
  // 判断编辑模式为绘制
  auto& state = query.get_resource<state::State>();
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();

  if (state.getDrawingMode() != state::DrawingModeType::Text)
    return;

  {
    auto& ol = query.get_resource<ol::Models>();

    uint32_t currentLayer = 0;
    if (state.getCurrentLayer(currentLayer)) {
      bool currentLayerHide = ol.currentLayerIsHide(currentLayer);
      if (currentLayerHide) {
        exit(query);
        return;
      }
    }
  }

  auto& select_models = query.get_resource<select::OverallModel>();
  // select_models.mouse_press = false;
  // select_models.mouse_release = false;

  // 获取cell和reg
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;

  // 获取输入 坐标系 撤销恢复
  auto& handModule = query.get_resource<vsg::ref_ptr<input::HandleBundle>>();
  auto& axisModule = query.get_resource<axis::Axis>();
  auto& undoRedoModule = query.get_resource<undoRedoT::UndoRedoModule>();

  // 获取参数
  auto& param = query.get_resource<Models>();
  auto& entity = param.entity;

  // 获取事件写入器
  auto event_writer = query.get_event_writer<draw::Event>();

  {
    uint32_t layer;
    if (!state.getCurrentLayer(layer)) {
      QMessageBox::information(nullptr, QObject::tr("error"), QObject::tr("No layer selected, unable to draw"));
      exit(query);
      return;
    }
  }

  stateTransformBegin(param, state, handModule, bus);

  if (param.state == State::Cancel)
    exit(query);

  // 获取当前鼠标点
  layout::Vec2d pos = {axisModule.real_x, axisModule.real_y};

  // 更新流程
  if (param.state == State::Upatde) {
    // 对象为空则新建
    if (entity == entt::null) {
      // 新建实体和指针
      entity = reg.create();
      auto label_ptr = qlib::Text::create();

      // 绑定指针到实体
      reg.emplace<qlib::Text::s_ptr>(entity, label_ptr);

      // 设置参数
      label_ptr->text = param.str;
      label_ptr->layer = param.layer;
      label_ptr->anchor = param.refer_point_pos;
      label_ptr->rotation = param.rotation;
      label_ptr->fontSize = param.size;

      // 设置位置
      label_ptr->origin = pos;

      // 通知外部更新
      add_cache_obj(reg, event_writer, layout_cmd, entity, param, query);
      param.clear_tag = true;
    } else {
      // 对象不为空则获取
      auto& label_ptr = reg.get<qlib::Text::s_ptr>(entity);

      // 读取参数
      label_ptr->text = param.str;
      label_ptr->layer = param.layer;
      label_ptr->anchor = param.refer_point_pos;
      label_ptr->rotation = param.rotation;
      label_ptr->fontSize = param.size;

      // 设置位置
      label_ptr->origin = pos;

      // 通知外部更新
      update_cache_obj(reg, event_writer, layout_cmd, entity, param);
      param.clear_tag = true;
    }
  }

  // 完成逻辑
  if (param.state == State::Complete) {
    // 新建实体和指针
    auto new_entity = reg.create();
    auto label_ptr = qlib::Text::create();

    // 绑定指针到实体
    reg.emplace<qlib::Text::s_ptr>(new_entity, label_ptr);

    // 设置参数
    label_ptr->text = param.str;
    label_ptr->layer = param.layer;
    label_ptr->anchor = param.refer_point_pos;
    label_ptr->rotation = param.rotation;
    label_ptr->fontSize = param.size;

    // 设置位置
    label_ptr->origin = pos;

    // 直接完成
    add_obj(reg, event_writer, layout_cmd, new_entity, undoRedoModule, cell, param, query, state);
    param.clear_tag = true;

    param.count++;
    param.str = param.string_arr[param.count % param.string_arr.size()];

    // // undoRedo
    // undoRedoModule.start(cell);
    // undoRedoModule.add(new_entity);
    // undoRedoModule.end();
  }

  stateTransformEnd(param.state);
}

void Plugin::build(ecs::App& app) {
  app.add_stage<InitStage>();
  app.add_stage<UpdateStage>();

  app.add_systems<InitStage>(init);
  app.add_systems<UpdateStage>(update);
  app.add_systems<ecs::stage::Last>(clear_tag);
}

}  // namespace qbe::draw::text